package com.caiyi.financial.nirvana.sms.queue;

import com.alibaba.fastjson.JSON;
import com.caiyi.financial.nirvana.sms.entity.SmsMsg;
import com.caiyi.financial.nirvana.sms.enums.MessageActionEnum;
import com.caiyi.financial.nirvana.sms.enums.SmsMsgStatusEnum;
import com.caiyi.financial.nirvana.sms.jedis.JedisKey;
import com.caiyi.financial.nirvana.sms.jedis.JedisService;
import com.caiyi.financial.nirvana.sms.service.SmsMsgService;
import com.caiyi.financial.nirvana.sms.task.PushReportTask;
import com.caiyi.financial.nirvana.sms.task.UpdateMsgTask;
import com.caiyi.financial.nirvana.sms.util.CommUtil;
import com.caiyi.financial.nirvana.sms.util.ThreadPoolUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by Mario on 2017/12/20 0020.
 * 短信入库队列
 */
@Component
public class InsertMessageQueue implements IRedisQueue {

    public static final Logger logger = LoggerFactory.getLogger(InsertMessageQueue.class);

    private static final int MAX_CACHE_SIZE = 2000;
    private static final int INSERT_INTERVAL = 5 * 1000;
    private final Map<String, SmsMsg> sendQueueEntityCache = new HashMap<>();
    private long startTime = System.currentTimeMillis();

    @Autowired
    private SmsMsgService smsMsgService;

    @Override
    public String key() {
        return JedisKey.SMS_QUEUE_MSG_DB;
    }

    public void run(List<String> list) {
        if (list != null && !list.isEmpty()) {
            SendQueueEntity entity = JSON.parseObject(list.get(1), SendQueueEntity.class);
            if (entity.getAction().equals(MessageActionEnum.INSERT.index)) {
                SmsMsg smsMsg = new SmsMsg();
                //新数据插入
                smsMsg.setProvince(entity.getProvince());
                smsMsg.setCity(entity.getCity());

                smsMsg.setBatchId(entity.getBatchId());
                smsMsg.setMessageId(entity.getMessageId());
                smsMsg.setAccount(entity.getAccount());
                smsMsg.setPhone(entity.getPhone());
                smsMsg.setContent(entity.getContent());
                smsMsg.setIp(entity.getIp());
                smsMsg.setNum(entity.getNum());
                smsMsg.setOperator(entity.getOperator());
                smsMsg.setAccessNumber(entity.getAccessNumber());
                smsMsg.setGatewayId(entity.getGatewayId());
                //补充默认数据
                smsMsg.setStatus(entity.getStatus());
                smsMsg.setResult(entity.getResult());
                smsMsg.setSendTime(entity.getSendTime());
                smsMsg.setCreateTime(new Date());
                smsMsg.setUpdateTime(new Date());
                smsMsg.setReceiveTime(new Date());
                //给推送时使用
                entity.setReceiveTime(new Date());
                sendQueueEntityCache.put(smsMsg.getMessageId(), smsMsg);
                CommUtil.M2B.put(entity.getMessageId(), entity);
            } else if (entity.getAction().equals(MessageActionEnum.RESPONSE.index)) {
                if (sendQueueEntityCache.containsKey(entity.getMessageId())) {
                    SmsMsg smsMsg = sendQueueEntityCache.get(entity.getMessageId());
                    //响应信息更新
                    smsMsg.setStatus(entity.getStatus());
                    smsMsg.setResult(entity.getResult());
                } else {
                    SmsMsg smsMsg = new SmsMsg();
                    smsMsg.setMessageId(entity.getMessageId());
                    smsMsg.setStatus(entity.getStatus());
                    smsMsg.setResult(entity.getResult());
                    this.updateMsg(smsMsg);
                }
                //设置接收时间给推送用
                entity.setReceiveTime(new Date());
            } else if (entity.getAction().equals(MessageActionEnum.CALLBACK.index)) {
                if (sendQueueEntityCache.containsKey(entity.getMessageId())) {
                    SmsMsg smsMsg = sendQueueEntityCache.get(entity.getMessageId());
                    //回调信息更新
                    smsMsg.setReceiveTime(entity.getReceiveTime());
                    smsMsg.setStatus(entity.getStatus());
                    smsMsg.setResult(entity.getResult());
                } else {
                    SmsMsg smsMsg = new SmsMsg();
                    smsMsg.setMessageId(entity.getMessageId());
                    smsMsg.setReceiveTime(entity.getReceiveTime());
                    smsMsg.setStatus(entity.getStatus());
                    smsMsg.setResult(entity.getResult());
                    this.updateMsg(smsMsg);
                }
            }
            //推送消息
            if (SmsMsgStatusEnum.SEND_SUCCESS.index == entity.getStatus() ||
                    SmsMsgStatusEnum.SEND_FAIL.index == entity.getStatus() ||
                    SmsMsgStatusEnum.REQUEST_FAIL.index == entity.getStatus()) {
                SendQueueEntity pushEntity = CommUtil.M2B.remove(entity.getMessageId());
                if (null == pushEntity) {
                    return;
                }
                if (pushEntity != null && StringUtils.isBlank(entity.getBatchId())) {
                    entity.setBatchId(pushEntity.getBatchId());
                    entity.setAccount(pushEntity.getAccount());
                    entity.setPhone(pushEntity.getPhone());
                    entity.setUid(pushEntity.getUid());
                    entity.setNotifyUrl(pushEntity.getNotifyUrl());
                }
                pushMsg(entity);
            }

        }
        boolean batch = this.sendQueueEntityCache.size() == MAX_CACHE_SIZE || (System.currentTimeMillis() - this.startTime) > INSERT_INTERVAL;
        batch = batch && this.sendQueueEntityCache.size() > 0;
        if (batch) {
            //开始处理
            this.sendQueueInsert(this.sendQueueEntityCache);
            //清空
            this.sendQueueEntityCache.clear();
            //时间重置
            this.startTime = System.currentTimeMillis();
        }
    }

    @Override
    public void interrupt(Exception e) {
        logger.info("连接中断,处理缓存数据...");
        this.sendQueueInsert(this.sendQueueEntityCache);
    }

    /**
     * 发送队列入库
     *
     * @param smsMsgMap 队列对象
     */
    private void sendQueueInsert(Map<String, SmsMsg> smsMsgMap) {
        List<SmsMsg> toInsert = new ArrayList<>(smsMsgMap.values());
        if (!toInsert.isEmpty()) {
            try {
                //插入数据库
                this.smsMsgService.insertList(toInsert);
            } catch (Exception e) {
                logger.error("InsertMessageQueue sendQueueInsert error ", e);
            }
        }
    }

    /**
     * 更新msg
     *
     * @param smsMsg msg
     */
    private void updateMsg(SmsMsg smsMsg) {
        UpdateMsgTask task = new UpdateMsgTask(this.smsMsgService, smsMsg);
        ThreadPoolUtil.EXECUTOR_UPDATE_MESSAGE.execute(task);
    }

    /**
     * 推送msg
     *
     * @param pushEntity
     */
    private void pushMsg(SendQueueEntity pushEntity) {
        //将需要主动回调的放入队列中
        if (StringUtils.isBlank(pushEntity.getNotifyUrl())) {
            String key = String.format(JedisKey.SMS_QUEUE_REPORT_LIST_ACCOUNT, pushEntity.getAccount());
            //是否为CMPP状态报告
            if (pushEntity.getAccount().length() == 6 && StringUtils.isNumeric(pushEntity.getAccount())) {
                logger.info("this is cmpp account : {}", pushEntity.getAccount());
                key = String.format(JedisKey.SMS_QUEUE_CMPP_REPORT_LIST_ACCOUNT, pushEntity.getAccount());
            }
            Map map = new HashMap();
            map.put("result", pushEntity.getResult());
            map.put("receiveTime", CommUtil.YYYY_MM_DD_HH_MM_SS.get().format(pushEntity.getReceiveTime()));
            map.put("status", pushEntity.getStatus());
            map.put("uid", pushEntity.getUid());
            map.put("phone", pushEntity.getPhone());
            map.put("batchId", pushEntity.getBatchId());
            map.put("account", pushEntity.getAccount());
            String json = JSON.toJSONString(map);
            JedisService.rpush(key, json);
            logger.info("InsertMessageQueue pushMsg msg : {}", json);
            return;
        }

        if (!isUrl(pushEntity.getNotifyUrl())) {
            logger.warn("InsertMessageQueue pushMsg NotifyUrl error : {}", pushEntity);
            return;
        }

        PushReportTask task = new PushReportTask(pushEntity);
        ThreadPoolUtil.EXECUTOR_PUSH_MESSAGE.execute(task);
    }

    /**
     * 校验是否为url
     *
     * @param url
     * @return
     */
    public static boolean isUrl(String url) {
        if (null == url) {
            return false;
        }
        String check = "^([hH][tT]{2}[pP]:/*|[hH][tT]{2}[pP][sS]:/*|[fF][tT][pP]:/*)(([A-Za-z0-9-~]+).)+([A-Za-z0-9-~\\/])+(\\?{0,1}(([A-Za-z0-9-~]+\\={0,1})([A-Za-z0-9-~]*)\\&{0,1})*)$";
        Pattern pattern = Pattern.compile(check);
        Matcher matcher = pattern.matcher(url);
        return matcher.matches();
    }


}
